{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "刘大拿\n"
     ]
    }
   ],
   "source": [
    "# 变量的三种用法\n",
    "\n",
    "class A():\n",
    "    def __init__(self):\n",
    "        self.name = \"haha\"\n",
    "        self.age = 18\n",
    "        \n",
    "a = A()\n",
    "# 属性的三种用法\n",
    "# 1.赋值\n",
    "# 2.读取\n",
    "# 3.删除\n",
    "a.name = \"刘大拿\"\n",
    "print(a.name)\n",
    "del a.name\n",
    "# print(a.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "haha\n",
      "我被读取了\n",
      "haha\n"
     ]
    }
   ],
   "source": [
    "# 类属性 property\n",
    "# 应用场景：\n",
    "# 对变量除了普通的三种操作，还想增加一些附加的操作，那么可以通过property完成\n",
    "class A():\n",
    "    def __init__(self):\n",
    "        self.name = \"haha\"\n",
    "        self.age = 18\n",
    "    # 此功能，是对类变量进行读取操作的时候应该执行的函数功能\n",
    "    def fget(self):\n",
    "        print(\"我被读取了\")\n",
    "        return self.name\n",
    "    # 模拟的是对变量进行写操作的时候执行的功能\n",
    "    def fset(self,name):\n",
    "        print(\"我被写入了，但是还可以做好多事情\")\n",
    "        self.name = \"图灵学院\" + name\n",
    "        \n",
    "    # fdel模拟的是删除变量的时候进行的操作\n",
    "    def fdel(self):\n",
    "        pass\n",
    "    \n",
    "    # property的四个参数顺序是固定的\n",
    "    # 第一个参数代表读取的时候需要调用的函数\n",
    "    # 第二个参数代表写入的时候需要调用的函数\n",
    "    # 第三个是删除\n",
    "    name2 = property(fget,fset,fdel,\"这是一个property的例子\")\n",
    "    \n",
    "a = A()\n",
    "print(a.name)\n",
    "\n",
    "print(a.name2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "闻一下对方\n",
      "Kiss me\n"
     ]
    }
   ],
   "source": [
    "# 抽象\n",
    "\n",
    "class Animel():\n",
    "    pass\n",
    "    '''\n",
    "    \n",
    "    def sayHello(self):\n",
    "        pass\n",
    "    '''\n",
    "    \n",
    "class Dog(Animel):\n",
    "    \n",
    "    def sayHello(self):\n",
    "        print(\"闻一下对方\")\n",
    "\n",
    "class Person(Animel):\n",
    "    \n",
    "    def sayHello(self):\n",
    "        print(\"Kiss me\")\n",
    "\n",
    "d = Dog()\n",
    "d.sayHello()\n",
    "\n",
    "p = Person()\n",
    "p.sayHello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 抽象类的实现\n",
    "\n",
    "import abc\n",
    "\n",
    "# 声明一个类并且指定当前类的元类\n",
    "class Human(metaclass=abc.ABCMeta):\n",
    "    \n",
    "    # 定义一个抽象方法\n",
    "    @abc.abstractmethod\n",
    "    def smoking(self):\n",
    "        pass\n",
    "    \n",
    "    # 定义类抽象方法\n",
    "    @abc.abstractclassmethod\n",
    "    def drink():\n",
    "        pass\n",
    "    \n",
    "    # 定义静态抽象方法\n",
    "    @abc.abstractstaticmethod\n",
    "    def play():\n",
    "        pass\n",
    "    \n",
    "    def sleep(self):\n",
    "        print(\"Sleeping......\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "月月你好，来一发吗？\n",
      "yueyue你好，来一发吗？\n"
     ]
    }
   ],
   "source": [
    "# 函数名可以当变量使用\n",
    "\n",
    "def sayHello(name):\n",
    "    print(\"{0}你好，来一发吗？\".format(name))\n",
    "    \n",
    "sayHello(\"月月\")\n",
    "\n",
    "liumang = sayHello\n",
    "\n",
    "liumang(\"yueyue\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saying......\n",
      "Saying......\n",
      "Saying......\n"
     ]
    }
   ],
   "source": [
    "# 自己组装一个类\n",
    "\n",
    "class A():\n",
    "    pass\n",
    "\n",
    "def say(self):\n",
    "    print(\"Saying......\")\n",
    "\n",
    "class B():\n",
    "    def say(self):\n",
    "        print(\"Saying......\")\n",
    "\n",
    "say(9)\n",
    "\n",
    "A.say = say\n",
    "\n",
    "a = A()\n",
    "a.say()\n",
    "\n",
    "b = B()\n",
    "b.say()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saying......\n"
     ]
    }
   ],
   "source": [
    "# 组装类例子 2\n",
    "# 自己组装一个类\n",
    "from types import MethodType\n",
    "\n",
    "class A():\n",
    "    pass\n",
    "\n",
    "def say(self):\n",
    "    print(\"Saying......\")\n",
    "    \n",
    "a = A()\n",
    "a.say = MethodType(say,A)\n",
    "a.say()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saying......\n",
      "Talking......\n"
     ]
    }
   ],
   "source": [
    "# 利用type造一个类\n",
    "\n",
    "# 先定以类应该具有的成员函数\n",
    "def say(self):\n",
    "    print(\"Saying......\")\n",
    "    \n",
    "def talk(self):\n",
    "    print(\"Talking......\")\n",
    "    \n",
    "# 用type来创建一个类\n",
    "A = type(\"AName\",(object,),{\"class_say\":say,\"class_talk\":talk})\n",
    "\n",
    "# 然后可以像正常方法访问一样使用类\n",
    "a = A()\n",
    "a.class_say()\n",
    "a.class_talk()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元类演示\n",
    "\n",
    "# 元类写法是固定的，他必须继承子type\n",
    "# 元类一般命名以MulignMetaClass结尾\n",
    "class TulingMetaClass(type):\n",
    "    # 注意以下写法\n",
    "    def __new__(cls,name,bases,attrs):\n",
    "        # 自己的业务处理\n",
    "        print(\"哈哈，我是元类啊\")\n",
    "        attrs['id'] = '000000'\n",
    "        attrs['addr'] = \"北京海淀区公主坟西翠路12号\"\n",
    "        return type.__new__(cls,name,bases,attrs)\n",
    "    \n",
    "# 元类定义完就可以使用，使用注意写法\n",
    "class Teacher(object,metaclass=TulingMetaClass):\n",
    "    pass\n",
    "\n",
    "t = Teacher()\n",
    "\n",
    "t.id"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
